package org.game.manager;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.bean.PlayerInfo;
import org.constant.MailConstant;
import org.game.cache.OnlinePlayerCache;
import org.game.cache.ServerCache;
import org.game.db.bean.Mail;
import org.game.db.bean.Player;
import org.game.db.bean.ServerMail;
import org.game.db.cache.MailCache;
import org.game.db.cache.ServerMailCache;
import org.game.db.vo.BaseMail;
import org.game.log.MailLog;
import org.game.log.builder.LogDsp;
import org.game.log.dsp.GoodsDsp;
import org.game.module.core.LoginMsgSender;
import org.game.module.mailbo.MailBO;
import org.game.msgBuilder.MailMsgBuilder;
import org.game.protobuf.s2c.S2CMailMsg.MailInfoList;
import org.game.protobuf.s2c.S2CShareMsg.ChangeType;
import org.game.util.ProtoUnit;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.sojoys.artifact.factory.message.IMessage;
import com.sojoys.artifact.manager.MessageManager;
import com.sojoys.artifact.manager.ThreadManager;
import com.sojoys.artifact.tools.ToolMap;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.RandomUtil;

/**
 * 邮件管理器
 * Created by fxf on 2017/7/25.
 */
public class MailManager implements LoginMsgSender {

    private static MailManager instance = new MailManager();

    private MailManager() {
    }

    public static MailManager me() {
        return instance;
    }

    @Override
    public void sendLoginMsg(Player player) {
//        List<Mail> mails = MailCache.me().getByPlayerId(player.getId());
//        if (!mails.isEmpty()) {
//            S2CMailMsg.LoginMailMsg.Builder builder = S2CMailMsg.LoginMailMsg.newBuilder();
//            mails.forEach((mail) -> {
//                S2CMailMsg.Mail.Builder mailBuilder = MailManager.me().createMailMsg(mail);
//                builder.addMailList(mailBuilder);
//            });
//            player.getSession().sendMessage(MessageManager.newMesssage(MailBO.sendLoginMsg, builder.build().toByteArray()));
//        }
    }

    /**
     * 发送单个邮件
     * @param senderPid			发件人ID
     * @param targetPid			收件人ID
     * @param title				标题
     * @param body				内容
     * @param items				附件
     * @param dsp				来自系统
     */
    public void sendPersonalMail(int senderPid,int targetPid,int textType,String titleKey, String bodyKey,Map bodyParam, Map<Integer, Integer> items,LogDsp logDsp) {
        Mail playerMail = createPlayerMail(senderPid, targetPid,textType, titleKey, bodyKey,bodyParam, items,logDsp);
        sendMail2Client(targetPid, playerMail);
        MailLog.logMail(targetPid, playerMail, MailLog.HANDLE_TYPE_CREATE_MAIL);
    }

    /**
     * 群发邮件
     *
     * @param senderPid      发送者id
     * @param targetPids 收件人ID列表
     * @param titleKey         邮件标题
     * @param bodyKey          邮件正文
     * @param items   资源列表
     * @param dsp           资源描述
     */
    public void sendMassMail(int senderPid, List<Integer> targetPids,int textType, String titleKey, String bodyKey,Map bodyParam,Map<Integer, Integer> items,LogDsp logDsp) {
        Collection<PlayerInfo> playerInfos = ServerCache.getPlayerInfoList(targetPids);
        ThreadPoolTaskExecutor task = ThreadManager.me().getThreadPoolTaskExecutor("taskExecutor");
        task.execute(() -> playerInfos.forEach(info -> {
            Mail mail = createPlayerMail(senderPid, info.getPid() ,textType, titleKey,bodyKey,bodyParam, items, logDsp);
            MailLog.logMail(info.getPid(), mail, MailLog.HANDLE_TYPE_CREATE_MAIL);
            sendMail2Client(info.getPid(), mail);
        }));
    }
    
    public List<BaseMail> getPlayerAllMails(Player player){
    	List<BaseMail> mails = Lists.newArrayList();
    	mails.addAll(player.getMailsFkPlayerId());
    	
    	List<ServerMail> serverMails = ServerMailCache.me().getCacheAll();
    	for (ServerMail serverMail : serverMails) {
    		int status = ToolMap.getInt(player.getId(), serverMail.getPidsStatus(),MailConstant.STATUS_DEFAULT);
    		// 邮件时间在玩家注册之前
			if (serverMail.getCreateDate().before(player.getRegisterDate())) {
				continue;
			}
    		if(status != MailConstant.STATUS_DELETE){
    			mails.add(serverMail);
    		}
		}
    	
    	return mails;
    }

    /**
     * 发送全服邮件
     *
     * @param senderPid     发送者id
     * @param senderName   发送者名字
     * @param titleKey        邮件标题
     * @param bodyKey         邮件正文
     * @param items  资源map
     * @param dsp          描述
     * @param dateOfExpiry 过期时间
     */
    public void sendServerMail(String uniqueId,int senderPid,int textType, String titleKey, String bodyKey,Map bodyParam,Map<Integer, Integer> items,LogDsp logDsp) {

    	ServerMail serverMail = createServerMail(uniqueId,senderPid, textType, titleKey, bodyKey, items);

    	List<BaseMail> mails = new ArrayList<>(1);
    	mails.add(serverMail);

    	
        Collection<Player> all = OnlinePlayerCache.getAll();
        MailInfoList.Builder builder = null;
        for (Player player : all) {
        	builder = MailInfoList.newBuilder();
        	
        	builder.addAllMails(MailMsgBuilder.createMailInfoArray(player, ChangeType.ADD, mails));
        	
        	List<BaseMail> overflowMail = checkMailMaxLimit(player,getPlayerAllMails(player));
        	if (!overflowMail.isEmpty()) {
        		builder.addAllMails(MailMsgBuilder.createMailInfoArray(player, ChangeType.DELETE, overflowMail));
        	}
        	IMessage msg = MessageManager.me().create(MailBO.getMails, ProtoUnit.toByte(builder.build()));
        	player.getPlayerProxy().sendMsg(msg);
		}
    }

    /**
     * 发送邮件到客户端
     *
     * @param pid  玩家id
     * @param mail 邮件
     */
    private void sendMail2Client(int pid, BaseMail mail) {
        Player onlinePlayer = OnlinePlayerCache.getPlayerById(pid);
        if (onlinePlayer != null) {
        	List<BaseMail> mails = new ArrayList<>(1);
        	mails.add(mail);
        	
            MailInfoList.Builder builder = MailInfoList.newBuilder();
            	
        	builder.addAllMails(MailMsgBuilder.createMailInfoArray(onlinePlayer, ChangeType.ADD, mails));
        	
        	List<BaseMail> overflowMail = checkMailMaxLimit(onlinePlayer,getPlayerAllMails(onlinePlayer));
        	if (!overflowMail.isEmpty()) {
        		builder.addAllMails(MailMsgBuilder.createMailInfoArray(onlinePlayer, ChangeType.DELETE, overflowMail));	
			}
        	IMessage msg = MessageManager.me().create(MailBO.getMails, ProtoUnit.toByte(builder.build()));
        	onlinePlayer.getPlayerProxy().sendMsg(msg);
        }
    }

    /**
     * 创建用户邮件
     * @param senderPid 		发件人ID
     * @param targetPid	收件人ID
     * @param title			标题
     * @param body			内容
     * @param dateOfExpiry
     * @param resourceMap
     * @param resourceDsp
     * @param callerCfgId
     * @return
     */
    private Mail createPlayerMail(int senderPid,  int targetPid, int textType, String title, String body,Map bodyParam ,Map<Integer, Integer> items,LogDsp logDsp) {
    	if (bodyParam == null) {
    		bodyParam = Maps.newHashMap();
		}
    	if (items == null) {
    		items = Maps.newHashMap();
		}
    	Mail mail = new Mail(0L, senderPid, targetPid, textType , title, body, bodyParam, items, MailConstant.STATUS_DEFAULT, logDsp.build());
        return mail.insert();
    }



    private ServerMail createServerMail(String uniqueId,int senderPid, int textType, String title, String body ,Map<Integer, Integer> items){
    	ServerMail serverMail = new ServerMail(0,uniqueId,senderPid, textType, title, body, items, Maps.newHashMap());
    	return serverMail.insert();
    }


    /**
     * 检查并删除超出上限的邮件
     * @return
     */
    public List<BaseMail> checkMailMaxLimit(Player player,List<BaseMail> mails){
    	int overflowMail = mails.size() - 100;
    	List<BaseMail> overflowMails = new ArrayList<>(Math.max(0, overflowMail));	
    	if (overflowMail > 0) {
    		Collections.sort(mails,(o1,o2) -> o1.getCreateDate().compareTo(o2.getCreateDate()));
    		overflowMails.addAll(mails.subList(0, overflowMail));
    		
    		
    		mails.removeAll(overflowMails);
    		
    		for (BaseMail baseMail : overflowMails) {
    			if (baseMail instanceof Mail) {
    				Mail mail =  (Mail) baseMail;
    				mail.delete();
    			}else if(baseMail instanceof ServerMail){
    				ServerMail mail = (ServerMail) baseMail;
    				mail.getPidsStatus().put(player.getId(), MailConstant.STATUS_DELETE);
    				mail.update();								
    			}
    		}
		}
    	return overflowMails;
    }
    
    
    public static void main(String[] args) throws InterruptedException {
    	Date date = null;
    	List<Date> lists = new ArrayList<>();
    	for (int i = 0; i < 5; i++) {
    		Thread.sleep(1000);
			date = new Date();
			lists.add(date);
		}
    	Collections.sort(lists,(o1,o2) -> o1.compareTo(o2));
    	
    	for (Date date2 : lists) {
			System.out.println(date2);
		}
    	System.out.println("--------------------------");
    	List<Date> newList = lists.subList(0, 2);
    	for (Date date2 : newList) {
    		System.out.println(date2);
		}
	}
    /**
     * 个人邮件过期检查并删除
     * @return
     */
    public List<Mail> checkTimeOutMail(List<Mail> mails) {
    	Date nowTime = new Date();
    	List<Mail> valid = Lists.newArrayList();
    	for (Mail mail : mails) {
    		if(mail.getStatus() == MailConstant.STATUS_DELETE){
    			mail.delete();
    		}else {
    			// 是否过期
    			boolean timeOut = DateUtil.betweenDay(mail.getCreateDate(), nowTime, true) > 7;
    			// 是否存在附件
//    			boolean items = (!mail.getItems().isEmpty() && mail.getStatus() != MailConstant.STATUS_RECEIVE);
//    			if (timeOut && !items) {
				if (timeOut) {
    				mail.delete();
    			}else {
    				valid.add(mail);
    			}
			}
		}
    	return valid;
    }

    /**
     * 服务器邮件过期检查
     */
    public boolean checkServerMailTimeOut(Player player,ServerMail serverMail){
    	Date nowTime = new Date();
		// 是否存在附件
		int status = ToolMap.getInt(player.getId(), serverMail.getPidsStatus(),MailConstant.STATUS_DEFAULT);
		if(status == MailConstant.STATUS_DELETE){
			return true;
		}else {
			// 邮件时间在玩家注册之前
			if (serverMail.getCreateDate().before(player.getRegisterDate())) {
				return true;
			}
			// 是否过期
			boolean timeOut = DateUtil.betweenDay(serverMail.getCreateDate(), nowTime, true) > 7;
//			boolean items = (!serverMail.getItems().isEmpty() && status != MailConstant.STATUS_RECEIVE);
//			if (timeOut && !items) {
			if (timeOut) {
				serverMail.getPidsStatus().put(player.getId(), MailConstant.STATUS_DELETE);
				serverMail.update();
				return true;
			}
		}
		return false;
    }

    public void sendGMMail(String uuid,int type, String title, String body, Map<Integer, Integer> item, Map bodyParam, List<Integer> playerIdList){
		if (type == MailConstant.MAIL_TYPE_PERSONAL){
			playerIdList.forEach(pid->{
				PlayerInfo playerInfo = ServerCache.getPlayerInfoByPid(pid);
				if (playerInfo==null) {
					// 可能是不属于当前服务器的邮件
					return;
				}
				sendPersonalMail(0,pid,MailConstant.TEXT_TYPE_DICT, title, body, bodyParam, item, LogDsp.newBuilder(GoodsDsp.GM_MAIL));
			});
		}else if (type == MailConstant.MAIL_TYPE_SERVER){
			sendServerMail(uuid, 0, MailConstant.TEXT_TYPE_DICT, title, body,bodyParam, item,LogDsp.newBuilder(GoodsDsp.GM_MAIL));
		}
	}

	public List<String> queryGMMail(int pid, long startTime, long endTime){
		List<Mail> allMail = MailCache.me().getByPlayerId(pid);
		List<String> result = allMail.stream()
				.filter(mail->mail.getSenderId() == 0)
				.filter(mail->mail.getCreateDate().getTime() >= startTime && mail.getCreateDate().getTime() <= endTime)
                .map(mail->mail.toJson())
				.collect(Collectors.toList());
		return result;
	}

//	public void testSendMoney(){
//		String title = "延迟开服补偿";
//			String body = "各位亲爱的dalao，晚上好：\n经过了一个日夜我们又修仙搞定了好几个BUG，在大家轮番攻陷中，修复BUG的我们又回来啦，大凉山指挥部准备再再再…再次给大家补偿2000钻。这次…还是下一次改BUG再见！\n比昨天更强了的大凉山制作组;";
//		Map<Integer,Integer> items = Maps.newHashMap();
//		items.put(500002,2000);
//		sendServerMail(UUID.randomUUID().toString(),0,MailConstant.TEXT_TYPE_DICT, title, body, items);
//	}

}
